package com.ciaojian.core.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ciaojian.core.enums.business.OrderOrderTypeEnum;
import com.ciaojian.core.model.Order;
import com.ciaojian.core.model.User;
import com.ciaojian.core.model.Worker;
import com.ciaojian.core.model.dto.FeesetCostDTO;
import com.ciaojian.core.model.dto.MemberDetailDTO;
import com.ciaojian.core.model.dto.OrderDTO;
import com.ciaojian.core.model.dto.WorkerDTO;
import com.ciaojian.core.model.vo.*;
import io.swagger.models.auth.In;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.annotations.Param;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author Atlakyn
 */
public interface OrderMapper extends BaseMapper<Order> {
    /**
     * 获取发型师差评订单
     *
     * @param page     分页插件
     * @param workerId 发型师ID
     * @param date     订单创建时间
     * @return 发型师差评订单
     */
    @MapKey(value = "id")
    Page<Map<String, Object>> getBadComment(Page<Map<String, Object>> page,
                                            @Param("workerId") Integer workerId,
                                            @Param("date") Date date);

    /**
     * 获取卡金充值订单详情
     *
     * @param orderId 订单ID
     * @return /
     */
    Map<String, Object> getChargeOrder(Integer orderId);

    /**
     * 新人特惠订单数
     *
     * @param storeId   门店ID
     * @param workerId  发型师ID
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return /
     */
    Integer countNewCustomerNum(@Param("storeId") Integer storeId,
                                @Param("workerId") Integer workerId,
                                @Param("startDate") Date startDate,
                                @Param("endDate") Date endDate);

    /**
     * 统计新老会员订单数
     *
     * @param storeId   门店
     * @param workerId  发型师
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return 新会员订单数和老会员订单数
     */
    Map<String, Integer> countNewAndOldMember(@Param("storeId") Integer storeId,
                                             @Param("workerId") Integer workerId,
                                             @Param("startDate") Date startDate,
                                             @Param("endDate") Date endDate);

    /**
     * 抖音会员转化数
     * <p>先抖音核销然后购买会员(中间没有其他订单)</p>
     *
     * @param workerId  发型师ID
     * @param storeId   门店ID
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return /
     */
    Integer countDouyinTurnMember(@Param("workerId") Integer workerId,
                                  @Param("storeId") Integer storeId,
                                  @Param("startDate") Date startDate,
                                  @Param("endDate") Date endDate);

    /**
     * 新人会员转化数
     *
     * @param storeId   门店ID
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return /
     */
    Integer countNewCustomerTurnMember(@Param("storeId") Integer storeId,
                                       @Param("startDate") Date startDate,
                                       @Param("endDate") Date endDate);

    /**
     * 员工业绩
     *
     * @param page    查询参数
     * @param param   分页插件
     * @param orderBy 排序字段
     * @return /
     */
    Page<Map<String, Object>> workerPerformance(Page<Map<String, BigDecimal>> page,
                                                @Param("param") MemberDetailDTO param,
                                                @Param("orderBy") Integer orderBy);

    /**
     * 门店业绩排行
     *
     * @param param 查询参数
     * @param page  分页插件
     * @return 业绩数据
     */
    Page<Map<String, BigDecimal>> storeRank(Page<Map<String, BigDecimal>> page,
                                            @Param("param") MemberDetailDTO param);

    /**
     * 销售总额 (含所有项目, 但不包括会员member_order)
     *
     * @param memberDetailDTO 查询参数
     * @return /
     */
    BigDecimal allSales(MemberDetailDTO memberDetailDTO);

    /**
     * 统计会员销售数据
     *
     * @param param /
     * @return /
     */
    List<Map<String, BigDecimal>> sumMemberSalesGroup(@Param("param") MemberDetailDTO param);

    /**
     * 统计会员销售数据
     *
     * @param month    月份
     * @param workerId 发型师ID
     * @return /
     */
    List<Map<String, Object>> sumMemberSales(@Param("month") String month, @Param("workerId") Integer workerId);

    /**
     * 查询超时订单<p>取号超过 90 分钟</p>
     *
     * @param date 日期
     * @return 超时订单
     */
//    @Select("SELECT * FROM d_order WHERE add_time <= #{date} AND status = 0")
    @Select("SELECT * FROM d_order WHERE add_time BETWEEN #{date1} and #{date} AND status = 0")
    List<Order> findOrderTimeOut(@Param("date1") Date date1,@Param("date") Date date);

    /**
     * 按月份统计门店销售额
     *
     * @param storeId   门店销售额
     * @param beginDate 开始时间
     * @param endDate   结束时间
     * @return 统计了总销售额、次卡销售额和美团销售额
     */
    List<Map<String, Object>> sumPayTotalByStoreIdEveryDay(@Param("storeId") Integer storeId,
                                                           @Param("beginDate") Date beginDate,
                                                           @Param("endDate") Date endDate);

    /**
     * 按月份统计门店销售额
     *
     * @param storeId 门店销售额
     * @return 统计了总销售额、次卡销售额和美团销售额
     */
    List<Map<String, Object>> sumPayTotalByStoreIdEveryMonth(@Param("storeId") Integer storeId, @Param("beginDate") Date beginDate,
                                                             @Param("endDate") Date endDate);

    /**
     * 按月份统计门店销售额
     *
     * @param storeId 门店销售额
     * @return 统计了总销售额、次卡销售额和美团销售额
     */
    List<Map<String, Object>> sumPayTotalByStoreIdEveryMonth1(@Param("storeId") Integer storeId);




    /**
     * 统计已完成订单的销售额
     *
     * @param storeId   门店Id 如果为空则查询全部的订单
     * @param orderType 订单类型 如果为空则查全部类型的订单
     * @param beginDate 开始时间
     * @param endDate   结束时间
     * @return 已完成订单的销售额(状态为 3 和 5)
     */
    @Select("SELECT IFNULL(SUM(pay_total),0) FROM d_order " +
            "WHERE status IN (3,5)" +
            "AND IF(#{storeId} IS NOT NULL, store_id = #{storeId},TRUE) " +
            "AND IF(#{orderType} IS NOT NULL,order_type = #{orderType}, TRUE)" +
            "AND add_time BETWEEN #{beginDate} AND #{endDate} ")
    BigDecimal sumPayTotalByStoreIdAndOrderTypeBetweenBeginDateAndEndDate(@Param("storeId") Integer storeId,
                                                                          @Param("orderType") OrderOrderTypeEnum orderType,
                                                                          @Param("beginDate") Date beginDate,
                                                                          @Param("endDate") Date endDate);

    /**
     * 统计已完成订单的销售额
     *
     * @param storeId 门店Id 如果为空则查询全部的订单
     * @return 已完成订单的销售额(状态为 3 和 5)
     */
    @Select("SELECT IFNULL(SUM(pay_total),0) FROM d_order " +
            "WHERE status IN (3,5)" +
            "AND IF(#{storeId} IS NOT NULL, store_id = #{storeId} ,TRUE)")
    BigDecimal sumPayTotal(@Param("storeId") Integer storeId);

    /**
     * 查询最近 7 天的新增消费用户数
     * <p>今天开始往前推 7 天</p>
     *
     * @param curDate 当前时间
     * @param storeId 门店Id
     * @return 最近 7 天的新增消费用户数
     */
    List<Map<String, Integer>> increaseOfLastWeek(@Param("curDate") Date curDate, @Param("storeId") Integer storeId);

    /**
     * 查询最近 4 周的新增消费用户数
     * <p>今天开始往前推 4 周</p>
     * <p>用第 n 周的方式来匹配</p>
     *
     * @param curDate 当前时间
     * @param storeId 门店Id
     * @return 最近 4 周的新增消费用户数
     */
    List<Map<String, Integer>> increaseOfWeek(@Param("curDate") Date curDate, @Param("storeId") Integer storeId);

    /**
     * 查询前 6 个月的新增消费用户数
     *
     * @param curDate 当前时间
     * @param storeId 门店Id
     * @return 前 6 个月的新增消费用户数
     */
    List<Map<String, Integer>> increaseOfMonth(@Param("curDate") Date curDate, @Param("storeId") Integer storeId);

    /**
     * 业绩薪酬页的我的订单接口
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param orderType 订单类型
     * @param workerId  发型师 id
     * @param pageNo    页码
     * @return 我的订单数据
     */
    Page<MyOrderVO> getMyOrder(Page<MyOrderVO> page,
                               @Param("startDate") Date startDate,
                               @Param("endDate") Date endDate,
                               @Param("orderType") Integer orderType,
                               @Param("workerId") Integer workerId,
                               @Param("pageNo") Integer pageNo
    );

    /**
     * 获取发型师当月的营业额
     *
     * @param workerId  发型师 id
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return 当月营业额
     */
    @Select("SELECT IFNULL(SUM(pay_total), 0)\n" +
            "FROM d_order AS o\n" +
            "WHERE o.pay_time BETWEEN #{startDate} AND #{endDate}  " +
            "  AND o.worker_id = #{workerId} " +
            "  AND status IN (3, 5)")
    BigDecimal getTurnoverOfWorker(@Param("workerId") Integer workerId,
                                   @Param("startDate") Date startDate,
                                   @Param("endDate") Date endDate);

    /**
     * 获取店面当月的营业额
     *
     * @param storeId   店面 id
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return 店面当月营业额
     */
    @Select("SELECT IFNULL(SUM(pay_total), 0) " +
            "FROM d_order AS o " +
            "WHERE o.pay_time BETWEEN #{startDate} AND #{endDate} " +
            "  AND o.store_id = #{storeId} " +
            "  AND status IN (3, 5) ")
    BigDecimal getTurnoverOfStore(@Param("storeId") Integer storeId,
                                  @Param("startDate") Date startDate,
                                  @Param("endDate") Date endDate);

    /**
     * 统计门店销售额
     *
     * @param storeId   门店Id
     * @param beginDate 开始时间
     * @param endDate   结束时间
     * @return 门店销售额
     */
    List<Map<String, Object>> sumSalesOfStore(@Param("storeId") Integer storeId,
                                              @Param("beginDate") Date beginDate,
                                              @Param("endDate") Date endDate);

    /**
     * 查找用户订单信息
     *
     * @param userId 用户id
     * @return 订单信息
     */
    @Select("SELECT worker_id,add_time " +
            "FROM (SELECT MAX(add_time) add_time, worker_id " +
            "      FROM d_order " +
            "      WHERE user_id = #{userId}  AND order_type IN (1, 9) " +
            "      GROUP BY worker_id) t " +
            "ORDER BY t.add_time DESC")
    @Results({
            @Result(property = "worker", column = "worker_id", javaType = WorkerDTO.class, one = @One(select = "com.ciaojian.core.mapper.WorkerMapper.selectWorkerDTO"))
    })
    List<OrderDTO> findByUserId(@Param("userId") Integer userId);

    /**
     * 查询发型师的等待服务和服务中的列表
     *
     * @param workerId 发型师 id
     * @return 订单列表
     */
    List<Map<String, Object>> findQueueByWorkerId(@Param("workerId") Integer workerId);


    /**
     * 店面本月销售额
     *
     * @param orderIds 店面 id 数组
     * @return 销售额
     */
    BigDecimal sumSales4month(Integer[] orderIds);


    /**
     * 查询时间范围内的销售额
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param orderIds  店面 id 集合
     * @return 时间范围内的销售额
     */
    Map<String, String> sumOrderNumAndSalesBetweenStartDateAndEndDate(Integer[] orderIds,
                                                                      @Param("startDate") Date startDate,
                                                                      @Param("endDate") Date endDate
    );

    /**
     * 查询时间范围内的客数
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param orderIds  店面 id 集合
     * @return 客数
     */
    Integer countCustomerNumBetweenStartDateAndEndDate(@Param("startDate") Date startDate,
                                                       @Param("endDate") Date endDate,
                                                       @Param("orderIds") Integer[] orderIds);

    /**
     * 查询销量最高服务
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param orderIds  店面 id 集合
     * @return 客数
     */
    String getServiceOfMostSales(@Param("startDate") Date startDate,
                                 @Param("endDate") Date endDate,
                                 @Param("orderIds") Integer[] orderIds);

    /**
     * 日期范围内的门店订单数
     *
     * @param id        门店 id
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return 订单数 Map
     */
    List<Map<String, String>> getNumBetweenStartDateAndEndDate(@Param("id") Integer id,
                                                               @Param("startDate") String startDate,
                                                               @Param("endDate") String endDate);

    /**
     * 查找门店客数
     *
     * @param storeId   门店 id
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return 生客
     */
    Map<String, Object> countCustomerByOrderId(@Param("storeId") Integer storeId,
                                               @Param("startDate") Date startDate,
                                               @Param("endDate") Date endDate);

    /**
     * 查找发型师生客
     *
     * @param workerId  发型师 id
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param storeId   门店 Id
     * @return 生客
     */
    Map<String, Object> countCustomerByWorkerId(@Param("workerId") Integer workerId,
                                                @Param("startDate") Date startDate,
                                                @Param("endDate") Date endDate,
                                                @Param("storeId") Integer storeId);

    // 查询用户订单列表
    List<Order> findUserOrder(String userId, String type);


    /**
     * 运营端查询发型师数据
     *
     * @param params /
     * @param page   分页插件
     * @return 订单集合
     */
    List<Object> findByOperationOrderQuery(@Param("params") Map params, Page page);

    /**
     * 查找排队用户
     *
     * @param workerId 发型师id
     * @return 正在排队的订单 按排队号升序
     */
    List<Order> getRankNext(@Param("workerId") Integer workerId);

    /**
     * @param title
     * @return
     */
    @Select("SELECT letter FROM d_haircut_service WHERE title = #{title}")
    String getLetter(String title);

    @Select("SELECT MAX(rank_no) FROM d_order WHERE store_id = #{storeId} AND rank_no LIKE '%${letter}%' AND TO_DAYS(add_time) = TO_DAYS(NOW())")
    String getDaysMaxrankNo(String storeId, String letter);

    @Select("SELECT dor.store_name,dor.rank_no,dw.`name`,dor.pay_total,dor.order_no,du.openid FROM d_order dor " +
            "LEFT JOIN d_worker dw ON dw.id = dor.worker_id " +
            "LEFT JOIN d_user du ON du.id = dor.user_id " +
            "WHERE dor.order_no = #{orderNo}")
    Order getOrderData(String orderNo);

    @Select("SELECT store_id FROM d_order WHERE order_no = #{orderNo} LIMIT 0,1")
    Integer getOrderStoreId(String orderNo);

    /**
     * 获取本单之前的等待订单列表
     *
     * @param workerId 发型师 id
     * @param orderNo  订单号
     * @return 订单列表
     */
    List<Map> findBeforeOrder(@Param("workerId") Integer workerId, @Param("orderNo") String orderNo);

    @Select("SELECT * FROM d_order WHERE STATUS=0 AND user_id=#{id} AND order_type IN(1,9)")
    List<OrderVo> getDOrderVo(Integer id);

    BigDecimal storeAmountCount(@Param("storeId") Integer storeId, @Param("startTime") Date startTime, @Param("endTime") Date endTime);

    Integer orderCount(@Param("storeId") Integer storeId, @Param("startTime") Date startTime, @Param("endTime") Date endTime);

    Integer countCutHairNum(@Param("storeId") Integer storeId, @Param("type") Integer type,@Param("startTime") Date startTime, @Param("endTime") Date endTime);

    BigDecimal storeAmountDouyin(@Param("storeId") Integer storeId, @Param("type") Integer type,@Param("startTime") Date startTime, @Param("endTime") Date endTime);

    Integer customerNum(@Param("storeId") Integer storeId, @Param("startTime") Date startTime, @Param("endTime") Date endTime);

    BigDecimal sumAmount(@Param("storeId") Integer storeId, @Param("workerId") Integer workerId, @Param("beginDate") Date beginDate, @Param("endDate") Date endDate);

    List<Worker> listByStoreId(@Param("storeId") Integer storeId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    List<ShoppingOrderVo> getShoppingOrder(@Param("userId") Integer userId);

    ShoppingOrderVo getShoppingOrderInfo(@Param("orderId") Integer orderId);

    Integer countDouyinChengeMember(@Param("workerId") Integer workerId, @Param("storeId") Integer storeId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    List<StoreMonthGapVo> getStoreMonthGap(@Param("storeId") Integer storeId, @Param("startTime") Date startTime, @Param("endTime") Date endTime);

    int checkHairOrderNum(@Param("userId") Integer userId);

    int checkMember(@Param("userId") Integer userId);

    List<SalesProfitVo> salesProfitList(@Param("storeId") Integer storeId, @Param("beginDate") Date beginDate, @Param("endDate") Date endDate);

    SalesProfitVo salesProfit(@Param("storeId") Integer storeId, @Param("beginDate") Date beginDate, @Param("endDate") Date endDate);

    List<SalesProfitVo> monthSalesCost(@Param("storeId") Integer storeId, @Param("beginDate") Date beginDate, @Param("endDate") Date endDate);

    Integer getRecordCount(@Param("distId") Integer distId);

    BigDecimal dySales(MemberDetailDTO memberDetailDTO);

    List<String> getHairTime(@Param("userId") Integer userId, @Param("lastMonth") Date lastMonth,@Param("nextMonth") Date nextMonth);

    Integer getHairWorkerCount(@Param("userId") Integer userId);

    Integer getServiceCount(@Param("userId") Integer userId);

    @Select("select pay_time\n" +
            "              FROM `d_order`\n" +
            "          where user_id  = #{userId}\n" +
            "            ORDER BY pay_time desc LIMIT 0,1")
    Date selectFreshTime(@Param("userId") Integer userId);

    List<WorkerCostVo> getWorkerCostVos(@Param("storeId") Integer storeId, @Param("beginDate") Date beginDate, @Param("endDate") Date endDate);

    List<FeesetCostVo> salesFeesetCost(@Param("storeId") Integer storeId, @Param("beginDate") Date beginDate, @Param("endDate") Date endDate);

    Integer getWorkerBad(@Param("storeId") Integer storeId, @Param("workerId") Integer workerId, @Param("beginDate") Date beginDate, @Param("endDate") Date endDate);

    Integer getworkerDay(@Param("storeId") Integer storeId, @Param("workerId") Integer workerId, @Param("beginDate") Date beginDate, @Param("endDate") Date endDate);

    Integer getTurnoverNum(@Param("workerId") Integer workerId, @Param("beginDate") Date beginDate, @Param("endDate") Date endDate);

    Page<Map<String, Object>> workerFeesetcost(@Param("page") Page<Map<String, BigDecimal>> page, @Param("param") FeesetCostDTO param, @Param("orderBy") Integer orderBy);

    Integer selectCouponCutNum(@Param("storeId") Integer storeId, @Param("workerId") Integer workerId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    List<Order> selectOrderNext(@Param("workerId") Integer workerId);

    SalesFranchiseesVo salesFranchisees(@Param("storeId") Integer storeId,@Param("orderType") Integer orderType, @Param("date") Date date, @Param("endDate") Date endDate);

    List<FranchiseesWorkerCountVo> workerOrdertotal(@Param("storeId") Integer storeId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    WorkerPerformanceVo workerPerformanceOne(@Param("workerId") Integer workerId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    List<Map<String, Object>> memberOrders(@Param("workerId") Integer workerId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    List<Map<String, Object>> userProportions(@Param("workerId") Integer workerId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    BigDecimal salesSalesToday(@Param("storeId") Integer storeId);

    Integer salesCutTodayCount(@Param("storeId") Integer storeId);

    Integer salesCutMonthCount(@Param("storeId") Integer storeId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    BigDecimal salesCutMonthSales(@Param("storeId") Integer storeId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    BigDecimal salesSalesMonth(@Param("storeId") Integer storeId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    Integer salesMemberMonthCount(@Param("storeId") Integer storeId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    BigDecimal salesMemberMonthSales(@Param("storeId") Integer storeId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);
}
